/*
Author: Saleem Hussain / saleem@sloan.mit.edu
STATUS
-2: Pre-Instructional step
-1: Instructional steps
0: Pre-Trial
1: In trial
2: Waiting for trial result input
3: Trial set complete
*/

var status = -2;

// CONFIGURATION
var trialRepeatN = 25;
var crosshairMS = 2000;
var primeMS = 75;
var blankMS = 125; //125;
var targetMS = 300; //100;
var retryDelay = 3000;
var screenDelay = 3000;
var longScreenDelay = 8000;
var retryN = 5;
var cfgId = "default";
var datastore = "jan2013";
var showSubjectId = false;
var imgDir = "pictographs2";
var scaling = "100";
var userinfo = "AppName="+navigator.userAgent+" AppVersion="+navigator.appVersion+" Platform="+navigator.platform;

var prime = null;
var neutral = null;

// COLLECTED TRIAL DATA
var subjectId =  null;
var subjectIdWithError = null;
var currentPrimeUrl = null;
var currentNeutralUrl = null;
var trialsCompleted=0;
var preFixationTime = null;
var startTime = null;
var preBlankTime = null;
var preTargetTime = null;
var preMaskTime = null;
var endTime = null;
var result = null; //left arrow = "NEGATIVE" which is "0", right arrow = "POSITIVE" which is "1"

// STORED TIME DATA
var fixDur =  null;
var primeDur =  null;
var blankDur =  null;
var targetDur =  null;
var maskDur =  null;

// WORKING VARIABLES
var config = null;
var currentInstruction = 0;
var currentStep = 0;
var numSteps = 0;
var numInstructions = 0;
var ignoreInput = false;
var waitTimer = false;

// CONSTANTS
var spacebarLabel = "Press the Space Bar to continue";
var waitingLabel = "Please wait...";

// YOUGOV SUPPORT
var visaId = null;

$(document).ready(function() {
	if(!window.console) console = {log: function() {}};
	setupLocalStorage();
	supportYouGovInit();
	$.get("config.xml", function(data){
		config = data;
		setupConfig();
		setSubjectId();
		nextStep();
	});
});

function setSubjectId()
{
	subjectId = +new Date;
	subjectIdWithError = subjectId;
	if (visaId != null)
	{
		subjectId = subjectId + "V" + visaId;
	}
}

function supportYouGovInit()
{
	if (getValue("visa") != "") // a config to be chosen from random?
	{
		visaId = getValue("visa");
	}
}

function nextStep()
{
	if (currentStep<numSteps)
	{
		// get type of next step
		var type = $(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+")").attr("type");
		console.log("Starting step "+currentStep+" of type "+type);
		if (type == "messages")
		{
			status = -2;
			numInstructions = $(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+") message").size();	
			currentInstruction = 0;
			showInstructions();
		
		}  else {
			if (type == "run")
			{
				status = 0;
				prepareRun();
			}
			currentStep++;
			
		}
	} 
}

function showInstructions()
{
	status = -1;
	var currentId = $(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+") message:eq("+currentInstruction+")").text();
	currentInstruction++;
	$("#AMP_cell").queue(function() {
		var messageString=addLiveDataToString($(config).find("message[id='"+currentId+"']").text());
		$(this).html(messageString);
		//$(this).load('config.xml #info001');
		$(this).dequeue();
	}); 
}

function prepareRun()
{
		if ($(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+")").attr("trialRepeatN") != null)
			trialRepeatN = parseInt($(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+")").attr("trialRepeatN"));
			
		if ($(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+")").attr("crosshairMS") != null)
			crosshairMS = parseInt($(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+")").attr("crosshairMS"));
		
		if ($(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+")").attr("primeMS") != null)
			primeMS = parseInt($(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+")").attr("primeMS"));
		
		if ($(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+")").attr("blankMS") != null)
			blankMS = parseInt($(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+")").attr("blankMS"));
			
		if ($(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+")").attr("targetMS") != null)
			targetMS = parseInt($(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+")").attr("targetMS"));
			
		if ($(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+")").attr("showSubjectId") != null)
			showSubjectId = ($(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+")").attr("showSubjectId") == "true");
			
		if ($(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+")").attr("datastore") != null)
			datastore = ($(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+")").attr("datastore"));
			
		if ($(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+")").attr("imgDir") != null)
			imgDir = ($(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+")").attr("imgDir"));
			
		if ($(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+")").attr("scaling") != null)
			scaling = ($(config).find("run-config[id='"+cfgId+"'] step:eq("+currentStep+")").attr("scaling"));
			
		prefetchCommonImages();
		fillArrays();
		pickRandom();
		executeTrial();

}

// DATA STORE
	
	function setupConfig()
	{
		if (getValue("set") != "") // a config to be chosen from random?
		{
			var configSet=getValue("set"); // the ID of the set in config
			console.log("Using configuration set "+configSet+"to determine configuration to use");
			var random = Math.random(); // pick a random number
			var randomCfgIds = new Array(); // build an array of possible options
			
			// build an array of probabilities associated with each option
			var randomCfgProb = new Array(); 
			$(config).find("config-set[id='"+configSet+"'] option").each(function(){
				console.log("Added config option of "+$(this).attr("id")+ " with probability "+parseFloat($(this).attr("p")));
				randomCfgIds.push($(this).attr("id"));
				randomCfgProb.push($(this).attr("p"));
			});
			console.log("Random number is "+random);
			
			// step through the options to decide which one is picked
			for (var i=0,p=0; i<randomCfgProb.length; i++)
			{
				p += parseFloat(randomCfgProb[i]);
				if (random<p || i==randomCfgProb.length-1)
				{
					cfgId=randomCfgIds[i]; // option is decided!
					break;
				}
			}
			
		} else if (getValue("id") != "") // specific config chosen?
		{
			cfgId=getValue("id");
		} 
		
		numSteps = $(config).find("run-config[id='"+cfgId+"'] step").size();	
		console.log("Configuration set to "+cfgId+" with "+numSteps+" steps");
	}

	function setupLocalStorage()
	{
		if (!localStorage["trials"]) {
		  localStorage["trials"] = JSON.stringify([]);
		}
	}

// TRIAL EXECUTION

$(document).keydown(function(e) {
if (!ignoreInput) {
	if (status == -2) {
		if (e.keyCode == 13)
		{
			// subjectId = document.getElementById("subjectid").value;
		} 
	} else if (status == -1)
	{
		if (e.keyCode == 32)
		{
			if (waitTimer)
			{
				console.log("Spacebar pressed without waiting 10 seconds");
			} else {
				if (currentInstruction<numInstructions)
				{	showInstructions();
				} else {
					currentStep++;
					nextStep();
				}
			}
		}
	} else if (status == 2)
	{
		if (e.keyCode == 73)
		{
			result = "1";
			postTrial();
		} else if (e.keyCode == 69)
		{
			result = "0";
			postTrial();
		} 
	} 
}
});

function consentResponse(cresponse)
{
	if (cresponse)
	{
		ignoreInput=false;
		$('#AMP_labels_left').show();$('#AMP_labels_right').show();
		if (currentInstruction<numInstructions)
			{	showInstructions();
			} else {
				currentStep++;
				nextStep();
		}
	} else {
		ignoreInput=true;
		$("#AMP_cell").queue(function() {
			var messageString=addLiveDataToString($(config).find("message[id='end_fail']").text());
			$(this).html(messageString);
			$(this).dequeue();
		}); 
	}
}

function postTrial()
{
	
	endTime = new Date;
	trialsCompleted++;
	var successReturn = logTrial();
	for (var i = 0; i<(retryN-1); i++) {
		if (successReturn) {
			console.log("Successfully stored in the database");	
			break;
		} else {
			console.log("Error storing in the database; waiting "+retryDelay+"ms before trying again...");
			pauseExecution(retryDelay);
			console.log("Trying again now...");
			successReturn = logTrial();
		}
	}
	if (!successReturn)
	{
		// console.log("Error storing in the database on final attempt; exiting out...");
		console.log("Error storing in the database on final attempt; continuing the set of trials...");
		subjectIdWithError += "e"+trialsCompleted+"e";
		// trialsCompleted = trialRepeatN;
	}
	if (trialsCompleted < trialRepeatN)
	{
		status = 0;
		pickRandom();
		executeTrial();							  
	} else {
		status = 3;
		trialsCompleted = 0;
		nextStep();
	}	
}

function pauseExecution(ms) {
	ms += new Date().getTime();
	while (new Date() < ms){}
} 



function executeTrial()
{
	// show crosshair
	$("#AMP_cell").queue(function() {
		preFixationTime = new Date;
		$(this).html('<img src="images/1-crosshair.gif" alt="" />');
		$(this).dequeue();
	});
	$("#AMP_cell").delay(crosshairMS);
	
	// show prime
	$("#AMP_cell").queue(function() {
		startTime = new Date;
		status = 1;
		$(this).html('<img src="'+currentPrimeUrl+'"  width="'+scaling+'" alt="" />');
		$(this).dequeue();
	});
	$("#AMP_cell").delay(primeMS);
	
	// show blank
	$("#AMP_cell").queue(function() {
		preBlankTime = new Date;
		$(this).html('');
		$(this).dequeue();
	});
	$("#AMP_cell").delay(blankMS);
	
	// show neutral
	$("#AMP_cell").queue(function() {
		preTargetTime = new Date;
		$(this).html('<img src="'+currentNeutralUrl+'"  width="'+scaling+'" alt="" />');
		$(this).dequeue();
	});
	$("#AMP_cell").delay(targetMS);
	
	// show mask
	  $("#AMP_cell").queue(function() {
		preMaskTime = new Date;
		$(this).html('<img src="images/Mask.jpg"  width="'+scaling+'" alt="" />');
		status = 2;
		$(this).dequeue();
	});
}

function pickRandom()
{
	console.log("Picking a random set of images");
	if (prime.length < 1 || neutral.length < 1)
	{
			console.log("Out of images; reloading");
			fillArrays();
			
	}
	currentPrimeUrl=prime.pop();
	currentNeutralUrl=neutral.pop();
	new Image().src = currentPrimeUrl;
	new Image().src = currentNeutralUrl;
	console.log("Prime img: "+currentPrimeUrl);
	console.log("Neutral img: "+currentNeutralUrl);
}



// USER INTERFACE

function fillArrays()
{
	console.log("Filling arrays with relevant images");
	prime = new Array();
	neutral = new Array();
	// hardcoding imgDir for backwards compatibility
	if (imgDir == "pictographs2")
	{
		for (var i=1; i<25; i++)	
		{
			prime.push(imgDir+"/neg"+i+".jpg");	
		}
		for (var i=1; i<25; i++)	
		{
			prime.push(imgDir+"/pos"+i+".jpg");	
		}
	} else if (imgDir == "pictographs3") {
		for (var j=1; j<9; j++)
		{
			for (var i=1; i<10; i++)	
			{
				prime.push(imgDir+"/cue"+i+".gif");	
			}
		}
	} else if (imgDir == "pictographs4") {
		for (var j=1; j<5; j++)
		{
			for (var i=1; i<13; i++)	
			{
				prime.push(imgDir+"/b"+i+".jpg");	
			}
			for (var i=1; i<13; i++)	
			{
				prime.push(imgDir+"/w"+i+".jpg");	
			}
		}
	}
	for (var i=1; i<201; i++)	
	{
		neutral.push(imgDir+"/pic"+i+".jpg");	
	}
	prime = randomizeArray(prime);
	neutral = randomizeArray(neutral);
}

function randomizeArray(srcArray)
{
	var s = [];
	while (srcArray.length) s.push(srcArray.splice(Math.random() * srcArray.length, 1));
	while (s.length) srcArray.push(s.pop());
	return srcArray;
}

function prefetchCommonImages()
{
	new Image().src = imgDir+"/Mask.jpg";
}

function showSeeResults()
{
	$("#AMP_cell").queue(function() {
		$(this).html('<a href="results.html">Click here to see results</a><br/>Or press any key to start a new trial set.');
		$(this).dequeue();
	});
}

function showEnterSubjectId()
{
	$("#AMP_cell").queue(function() {
		$(this).html('enter subject id and press enter:<br/><input name="subjectid" id="subjectid" type="textfield"/>');
		$(this).dequeue();
	});
}

function getValue(varname)
{
  var url = window.location.href;
  var qparts = url.split("?");
  if (qparts.length == 0)
  {
	return "";
  }
  var query = qparts[1];
  if (query == null) return "";
  var vars = query.split("&");
  var value = "";
  for (i=0;i<vars.length;i++)
  {
	var parts = vars[i].split("=");
	if (parts[0] == varname)
	{
	  value = parts[1];
	  break;
	}
  }
  value = unescape(value);
  value.replace(/\+/g," ");
  return value;
}

jQuery.create = function() {
	if (arguments.length == 0) return [];
	var args = arguments[0] || {}, elem = null, elements = null;
	var siblings = null;

	// In case someone passes in a null object,
	// assume that they want an empty string.
	if (args == null) args = "";
	if (args.constructor == String) {
		if (arguments.length > 1) {
			var attributes = arguments[1];
				if (attributes.constructor == String) {
							elem = document.createTextNode(args);
							elements = [];
							elements.push(elem);
							siblings =
		jQuery.create.apply(null, Array.prototype.slice.call(arguments, 1));
							elements = elements.concat(siblings);
							return elements;

					} else {
							elem = document.createElement(args);

							// Set element attributes.
							var attributes = arguments[1];
							for (var attr in attributes)
								jQuery(elem).attr(attr, attributes[attr]);

							// Add children of this element.
							var children = arguments[2];
							children = jQuery.create.apply(null, children);
							jQuery(elem).append(children);

							// If there are more siblings, render those too.
							if (arguments.length > 3) {
									siblings =
		jQuery.create.apply(null, Array.prototype.slice.call(arguments, 3));
									return [elem].concat(siblings);
							}
							return elem;
					}
			} else return document.createTextNode(args);
	  } else {
			  elements = [];
			  elements.push(args);
			  siblings =
		jQuery.create.apply(null, (Array.prototype.slice.call(arguments, 1)));
			  elements = elements.concat(siblings);
			  return elements;
	  }
};

function logTrial()
		{ 
			
			var xhr=getXMLHttpRequest(); 
			
			var fixDur=startTime.getTime()-preFixationTime.getTime();
			var primeDur=preBlankTime.getTime()-startTime.getTime();
			var blankDur=preTargetTime.getTime()-preBlankTime.getTime();
			var targetDur=preMaskTime.getTime()-preTargetTime.getTime();
			var maskDur=endTime.getTime()-preMaskTime.getTime();
			
			// console.log("mask duration is "+maskDur);
			
			var getrequest= "actions/logtrial.php?datastore="+datastore+"&cfgId="+cfgId+"&subjectId="+subjectId+"&currentPrime="+currentPrimeUrl+"&currentNeutral="+currentNeutralUrl+"&trialsCompleted="+trialsCompleted+"&startTime="+startTime.getTime()+"&fixDur="+fixDur+"&primeDur="+primeDur+"&blankDur="+blankDur+"&targetDur="+targetDur+"&maskDur="+maskDur+"&result="+result+"&userinfo="+userinfo;
		  	xhr.open("GET", getrequest,  false); 
		    xhr.send(null); 
		    var serverResponse = xhr.responseText;
		    var returnvalue = (serverResponse == "true");
			if (!returnvalue)
			{
				console.log(serverResponse);
			}
		    return returnvalue;
		} 
	
function getXMLHttpRequest()
	{
		var xhr;
		try {  xhr = new ActiveXObject('Msxml2.XMLHTTP');   }
		catch (e) 
		{
			try {   xhr = new ActiveXObject('Microsoft.XMLHTTP');    }
			catch (e2) 
			{
			  try {  xhr = new XMLHttpRequest();     }
			  catch (e3) {  xhr = false;   }
			}
		 }
		 return xhr;
}

function addLiveDataToString(stringVar)
{
	// keywords: (1) (subjectId), (2) (visaId), (3) (longspacebartime)
	var newString;
	newString = stringVar.replace("(subjectId)",subjectIdWithError);
	newString = newString.replace(/\(visaId\)/g,visaId);
	if (stringVar.indexOf("(spacebartimer)") != -1)
	{
		newString = stringVar.replace("(spacebartimer)",waitingLabel);
		waitTimer = true;
		setTimeout(function(){
			waitTimer = false;
			$("#AMP_cell").html($("#AMP_cell").html().replace(waitingLabel,spacebarLabel));
		},screenDelay);
	}
	if (stringVar.indexOf("(longspacebartimer)") != -1)
	{
		newString = stringVar.replace("(longspacebartimer)",waitingLabel);
		waitTimer = true;
		setTimeout(function(){
			waitTimer = false;
			$("#AMP_cell").html($("#AMP_cell").html().replace(waitingLabel,spacebarLabel));
		},longScreenDelay);
	}
	
	return newString;
	
}


